#pragma once
#include<pthread.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<functional>

namespace ThreadModule
{

    static uint32_t number = 1;
   //template<class T>
    class Thread
    {
        using func_t = std::function<void()>; //创建一个可调用对象类型
      private:
        void EnableDetach()
        {
            _isdetach = true;
        }

        void EnableRunning()
        {
            _isrunning = true;
        }
        
        static void* Routine(void* args) //采用静态成员函数，让第一参数不为this
        {
          Thread* self = static_cast<Thread*>(args); //通过传参拿到this指针
          self->EnableRunning();
          if(self->_isdetach)
            self->Detach();
          pthread_setname_np(self->_tid, self->_name.c_str());
          self->_func(); //回调处理
          return nullptr;
        }

      public:
        Thread(func_t func)
        :_tid(0), _isdetach(false), 
        _isrunning(false), _res(nullptr), 
        _func(func)
        {
            _name = "thread-" + std::to_string(number++); 
        }
        
        void Detach()
        {
            if(_isdetach)
              return;
            if(_isrunning)
              pthread_detach(_tid);
            EnableDetach();
        }

        bool Start()
        {
            if(_isrunning)
              return false;
            int n = pthread_create(&_tid, nullptr, Routine, this);
            if(n != 0)
              return false;
            else
              return true;
        }

        bool Stop()
        {
            if(_isrunning)
            {
               int n = pthread_cancel(_tid);
               if(n != 0)  return false;
               else
               {
                  _isrunning = false;
                  return true;
               }
            }
            return false;
        }

        void Join()
        {
            if(_isdetach)
             return;
            int n = pthread_join(_tid, &_res);
            (void)n;
        }

        std::string Name()
        {
           return _name;
        }
        
        ~Thread()
        {}

      private:
        pthread_t _tid;
        std::string _name;
        bool _isdetach;
        bool _isrunning;
        void * _res;//线程返回值
        func_t _func;
        //T _data;
    };
}